package com.example.demo;

import cn.hutool.core.util.ArrayUtil;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.ConfigBuilder;
import com.baomidou.mybatisplus.generator.config.converts.OracleTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableField;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.FileType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * mybatisplus代码生成
 *
 * @author TongDaShuai
 * @since 2021/8/13
 */
public class MpCodeGenerate {

    public static void main(String[] args) throws FileNotFoundException {

        // ------------------- 参数配置 ----------------------------
        // 数据库配置
        String dbUrl = "jdbc:oracle:thin:@127.0.0.1:1521/helowinXDB";
        dbUrl = "jdbc:mysql://localhost:50000/tds?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai";
        String driverName = "oracle.jdbc.driver.OracleDriver";
        driverName = "com.mysql.cj.jdbc.Driver";
        String userName = "tds";
        String password = "123789";
        // 包配置
        String moudule = "demo";
        String parentPackage = "com.example";
        // 多个表用逗号分割(不知道为啥，这里的表名小写不行，必须大写)
        String tablenames = "study_data";
        // 基础类路径
        String basePath = "com/example/demo";
        // Query类路径
        String queryPath = basePath + "/pojo/query";
        // pageVo类路径
        String pageVoPath = basePath + "/pojo/vo";
        // addDto类路径
        String addDtoPath = basePath + "/pojo/dto/add";
        // updateDto类路径
        String updateDtoPath = basePath + "/pojo/dto/update";
        // basequery类路径
        String baseQueryPackage = "com.example.demo.pojo.base";
        // 基础pojo类路径
        String basePojoPath = basePath + "/pojo";
        // 表前缀去除
        String[] rmPrefix = {"sys_"};
        // 子工程目录
//        String subProPath = "/supervise-huazhong";
        String subProPath = "";
        // 作者
        String author = "tds";
        // 是否生成controller、service
        boolean needController = true;
        boolean needService = true;
        // 是否需要分页查询
        boolean needSelectPage = true;
        // 是否需要新增
        boolean needAdd = true;
        // 是否需要修改
        boolean needUpdate = true;
        // 是否需要删除
        boolean needDelete = true;

        // 覆盖的文件类型
        FileType[] fileTypes = {
                FileType.CONTROLLER,
                FileType.ENTITY,
                FileType.SERVICE,
                FileType.SERVICE_IMPL,
                FileType.MAPPER,
                FileType.XML,
                FileType.OTHER
        };



        // ------------------ 参数配置end -----------------------

        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局配置
        GlobalConfig gc = new GlobalConfig();
//        String projectPath = path;
        String projectPath = System.getProperty("user.dir") + subProPath;
        gc.setOutputDir(projectPath + "/src/main/java");
        System.out.println(projectPath);
        gc.setAuthor(author);
        gc.setOpen(false);
        // gc.setSwagger2(true); 实体属性 Swagger2 注解
        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(dbUrl);
        // dsc.setSchemaName("public");
        dsc.setDriverName(driverName);
        dsc.setUsername(userName);
        dsc.setPassword(password);
        // 自定义类型转换
        dsc.setTypeConvert(new OracleTypeConvert(){
            @Override
            public IColumnType processTypeConvert(GlobalConfig globalConfig, TableField tableField) {
                // 将数据库中date转换成date
                if ( tableField.getType().toLowerCase().equals( "date" )) {
                    return DbColumnType.DATE;
                }
                return super.processTypeConvert(globalConfig, tableField);
            }
        });

        mpg.setDataSource(dsc);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(moudule);
        pc.setParent(parentPackage);
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                Map<String, Object> map = new HashMap<>();
                map.put("swagger", true);

                map.put("basePackage", ArrayUtil.join(basePath.split("/"), "."));
                map.put("basePojoPackage", ArrayUtil.join(basePojoPath.split("/"), "."));
                map.put("queryPachage", ArrayUtil.join(queryPath.split("/"), "."));
                map.put("pageVoPackage", ArrayUtil.join(pageVoPath.split("/"), "."));
                map.put("baseQueryPackage", baseQueryPackage);
                map.put("addDtoPackage", ArrayUtil.join(addDtoPath.split("/"), "."));
                map.put("updateDtoPackage", ArrayUtil.join(updateDtoPath.split("/"), "."));

                map.put("needSelectPage", needSelectPage);
                map.put("needAdd", needAdd);
                map.put("needUpdate", needUpdate);
                map.put("needDelete", needDelete);

                this.setMap(map);
            }
        };

        // 如果模板引擎是 freemarker
        String mapperTemplatePath = "/templates/mapper.xml.ftl";
        String queryTemplatePath = "/templates/query.java.ftl";
        String pageVoTemplatePath = "/templates/pageVo.java.ftl";
        String addDtoTemplatePath = "/templates/addDto.java.ftl";
        String updateDtoTemplatePath = "/templates/updateDto.java.ftl";

        // 如果模板引擎是 velocity
        // String mapperTemplatePath = "/templates/mapper.xml.vm";

        // 自定义输出配置
        List<FileOutConfig> focList = new ArrayList<>();
        // 自定义配置会被优先输出
        focList.add(genFileOutConfig(projectPath + "/src/main/resources/mapper/", mapperTemplatePath,
                "Mapper", StringPool.DOT_XML));
        focList.add(genFileOutConfig(projectPath + "/src/main/java/" + queryPath + "/", queryTemplatePath,
                "Query", StringPool.DOT_JAVA));
        focList.add(genFileOutConfig(projectPath + "/src/main/java/" + pageVoPath + "/", pageVoTemplatePath,
                "Vo", StringPool.DOT_JAVA));
        focList.add(genFileOutConfig(projectPath + "/src/main/java/" + addDtoPath + "/", addDtoTemplatePath,
                "AddDto", StringPool.DOT_JAVA));
        focList.add(genFileOutConfig(projectPath + "/src/main/java/" + updateDtoPath + "/", updateDtoTemplatePath,
                "UpdateDto", StringPool.DOT_JAVA));



        // 自定义文件生成
        cfg.setFileCreate(new IFileCreate() {
            @Override
            public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
                // 判断自定义文件夹是否需要创建
                checkDir(filePath);

                // 无论是否存在，都覆盖
                for (FileType type : fileTypes) {
                    if (fileType == type) {
                       return true;
                    }
                }

                // 其他文件不存在才创建
                return !new File(filePath).exists();
//                if (fileType == FileType.MAPPER) {
//                    // 已经生成 mapper 文件判断存在，不想重新生成返回 false
//                    return !new File(filePath).exists();
//                }
//
//
//                // 允许生成模板文件
//                return true;
            }
        });

        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();

        // 配置自定义输出模板
        //指定自定义模板路径，注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
//         templateConfig.setEntity("templates/entity.java");
//         templateConfig.setService("");
        // 不生成controller和mapper.xml，mapper.xml用自定义生成路径
        if (!needController) {
            templateConfig.setController(null);
        }
        if (!needService) {
            templateConfig.setService(null);
            templateConfig.setServiceImpl(null);
        }
        templateConfig.setXml(null);

        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
//        strategy.setSuperEntityClass("你自己的父类实体,没有就不用设置!");
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);


        // 公共父类
//        strategy.setSuperControllerClass("你自己的父类控制器,没有就不用设置!");
        // 写于父类中的公共字段
//        strategy.setSuperEntityColumns("id");
        strategy.setInclude(tablenames.split(","));
        strategy.setControllerMappingHyphenStyle(true);
        strategy.setTablePrefix(rmPrefix);
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());

        // 生成代码（可以跟踪进去看下）
        mpg.execute();
    }

//    private static FileOutConfig genFileOutConfig(String projectPath, String mapperTemplatePath) {
//        return new FileOutConfig(mapperTemplatePath) {
//            @Override
//            public String outputFile(TableInfo tableInfo) {
//                // 自定义输出文件名 ， 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化！！
//                return projectPath + "/src/main/resources/mapper/" +
//                        tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
//            }
//        };
//    }

    /**
     * 生成输出文件配置
     *
     * @param parentDir 父级目录
     * @param mapperTemplatePath 模板文件路径
     * @param fileNameSuffix  文件名称后缀
     * @param fileSuffix 文件名后缀
     * @return
     */
    private static FileOutConfig genFileOutConfig(String parentDir, String mapperTemplatePath, String fileNameSuffix, String fileSuffix) {
        return new FileOutConfig(mapperTemplatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return  parentDir + tableInfo.getEntityName() + fileNameSuffix + fileSuffix;
            }
        };
    }
}
